From 47b25fd357571368d19f83a09cd0f4595d4cf4e4 Mon Sep 17 00:00:00 2001 From: Kalita Alexey Date: Tue, 17 Jan 2017 22:23:48 +0300 Subject: [PATCH] Allow examples to be libraries --- src/cargo/core/manifest.rs | 45 +++++++++++++++++------- src/cargo/core/package.rs | 6 ++-- src/cargo/ops/cargo_compile.rs | 17 ++++----- src/cargo/ops/cargo_rustc/context.rs | 14 +++++--- src/cargo/ops/cargo_rustc/fingerprint.rs | 3 +- src/cargo/util/toml.rs | 11 +++++- 6 files changed, 66 insertions(+), 30 deletions(-) diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 86cd6eebd..f229281b8 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -104,18 +104,21 @@ pub enum TargetKind { Bin, Test, Bench, - Example, + ExampleLib(Vec), + ExampleBin, CustomBuild, } impl Encodable for TargetKind { fn encode(&self, s: &mut S) -> Result<(), S::Error> { match *self { - TargetKind::Lib(ref kinds) => { - kinds.iter().map(|k| k.crate_type()).collect() + TargetKind::Lib(ref kinds) | + // TODO: I am not sure whether it should be encoded like a library or like an example + TargetKind::ExampleLib(ref kinds) => { + kinds.iter().map(LibKind::crate_type).collect() } TargetKind::Bin => vec!["bin"], - TargetKind::Example => vec!["example"], + TargetKind::ExampleBin => vec!["example"], TargetKind::Test => vec!["test"], TargetKind::CustomBuild => vec!["custom-build"], TargetKind::Bench => vec!["bench"], @@ -341,9 +344,17 @@ impl Target { } } - pub fn example_target(name: &str, src_path: PathBuf) -> Target { + pub fn example_target(name: &str, + crate_targets: Vec, + src_path: PathBuf) -> Target { + let kind = if crate_targets.is_empty() { + TargetKind::ExampleBin + } else { + TargetKind::ExampleLib(crate_targets) + }; + Target { - kind: TargetKind::Example, + kind: kind, name: name.to_string(), benched: false, ..Target::with_path(src_path) @@ -415,7 +426,15 @@ impl Target { } pub fn is_bin(&self) -> bool { self.kind == TargetKind::Bin } - pub fn is_example(&self) -> bool { self.kind == TargetKind::Example } + + pub fn is_example(&self) -> bool { + match self.kind { + TargetKind::ExampleBin | + TargetKind::ExampleLib(..) => true, + _ => false + } + } + pub fn is_test(&self) -> bool { self.kind == TargetKind::Test } pub fn is_bench(&self) -> bool { self.kind == TargetKind::Bench } pub fn is_custom_build(&self) -> bool { self.kind == TargetKind::CustomBuild } @@ -423,13 +442,14 @@ impl Target { /// Returns the arguments suitable for `--crate-type` to pass to rustc. pub fn rustc_crate_types(&self) -> Vec<&str> { match self.kind { - TargetKind::Lib(ref kinds) => { - kinds.iter().map(|kind| kind.crate_type()).collect() - }, + TargetKind::Lib(ref kinds) | + TargetKind::ExampleLib(ref kinds) => { + kinds.iter().map(LibKind::crate_type).collect() + } TargetKind::CustomBuild | TargetKind::Bench | TargetKind::Test | - TargetKind::Example | + TargetKind::ExampleBin | TargetKind::Bin => vec!["bin"], } } @@ -478,7 +498,8 @@ impl fmt::Display for Target { TargetKind::Bin => write!(f, "Target(bin: {})", self.name), TargetKind::Test => write!(f, "Target(test: {})", self.name), TargetKind::Bench => write!(f, "Target(bench: {})", self.name), - TargetKind::Example => write!(f, "Target(example: {})", self.name), + TargetKind::ExampleBin | + TargetKind::ExampleLib(..) => write!(f, "Target(example: {})", self.name), TargetKind::CustomBuild => write!(f, "Target(script)"), } } diff --git a/src/cargo/core/package.rs b/src/cargo/core/package.rs index 11e53cf2c..e3ae1fded 100644 --- a/src/cargo/core/package.rs +++ b/src/cargo/core/package.rs @@ -6,7 +6,7 @@ use std::path::{Path, PathBuf}; use semver::Version; -use core::{Dependency, Manifest, PackageId, SourceId, Target, TargetKind}; +use core::{Dependency, Manifest, PackageId, SourceId, Target}; use core::{Summary, SourceMap}; use ops; use util::{CargoResult, Config, LazyCell, ChainError, internal, human, lev_distance}; @@ -94,10 +94,10 @@ impl Package { self.targets().iter().any(|t| t.is_custom_build()) } - pub fn find_closest_target(&self, target: &str, kind: TargetKind) -> Option<&Target> { + pub fn find_closest_target(&self, target: &str, is_expected_kind: fn(&Target)-> bool) -> Option<&Target> { let targets = self.targets(); - let matches = targets.iter().filter(|t| *t.kind() == kind) + let matches = targets.iter().filter(|t| is_expected_kind(t)) .map(|t| (lev_distance(target, t.name()), t)) .filter(|&(d, _)| d < 4); matches.min_by_key(|t| t.0).map(|t| t.1) diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index 8616774e0..870d80a8a 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -295,7 +295,8 @@ impl<'a> CompileFilter<'a> { TargetKind::Bin => bins, TargetKind::Test => tests, TargetKind::Bench => benches, - TargetKind::Example => examples, + TargetKind::ExampleBin | + TargetKind::ExampleLib(..) => examples, TargetKind::Lib(..) => return lib, TargetKind::CustomBuild => return false, }; @@ -374,15 +375,15 @@ fn generate_targets<'a>(pkg: &'a Package, } { - let mut find = |names: &[String], desc, kind, profile| { + let mut find = |names: &[String], desc, is_expected_kind: fn(&Target) -> bool, profile| { for name in names { let target = pkg.targets().iter().find(|t| { - t.name() == *name && *t.kind() == kind + t.name() == *name && is_expected_kind(t) }); let t = match target { Some(t) => t, None => { - let suggestion = pkg.find_closest_target(name, kind); + let suggestion = pkg.find_closest_target(name, is_expected_kind); match suggestion { Some(s) => { let suggested_name = s.name(); @@ -398,10 +399,10 @@ fn generate_targets<'a>(pkg: &'a Package, } Ok(()) }; - find(bins, "bin", TargetKind::Bin, profile)?; - find(examples, "example", TargetKind::Example, build)?; - find(tests, "test", TargetKind::Test, test)?; - find(benches, "bench", TargetKind::Bench, &profiles.bench)?; + find(bins, "bin", Target::is_bin, profile)?; + find(examples, "example", Target::is_example, build)?; + find(tests, "test", Target::is_test, test)?; + find(benches, "bench", Target::is_bench, &profiles.bench)?; } Ok(targets) } diff --git a/src/cargo/ops/cargo_rustc/context.rs b/src/cargo/ops/cargo_rustc/context.rs index a5a16b479..a46baaa86 100644 --- a/src/cargo/ops/cargo_rustc/context.rs +++ b/src/cargo/ops/cargo_rustc/context.rs @@ -133,6 +133,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { for unit in units { self.visit_crate_type(unit, &mut crate_types)?; } + debug!("probe_target_info: crate_types={:?}", crate_types); self.probe_target_info_kind(&crate_types, Kind::Target)?; if self.requested_target().is_none() { self.host_info = self.target_info.clone(); @@ -517,19 +518,22 @@ impl<'a, 'cfg> Context<'a, 'cfg> { }; match *unit.target.kind() { - TargetKind::Example | TargetKind::Bin | TargetKind::CustomBuild | + TargetKind::ExampleBin | TargetKind::Bench | TargetKind::Test => { add("bin", false)?; } - TargetKind::Lib(..) if unit.profile.test => { + TargetKind::Lib(..) | + TargetKind::ExampleLib(..) + if unit.profile.test => { add("bin", false)?; } - TargetKind::Lib(ref libs) => { - for lib in libs { - add(lib.crate_type(), lib.linkable())?; + TargetKind::ExampleLib(ref kinds) | + TargetKind::Lib(ref kinds) => { + for kind in kinds { + add(kind.crate_type(), kind.linkable())?; } } } diff --git a/src/cargo/ops/cargo_rustc/fingerprint.rs b/src/cargo/ops/cargo_rustc/fingerprint.rs index 3d1f27449..02ea5a47f 100644 --- a/src/cargo/ops/cargo_rustc/fingerprint.rs +++ b/src/cargo/ops/cargo_rustc/fingerprint.rs @@ -657,7 +657,8 @@ fn filename(cx: &mut Context, unit: &Unit) -> String { TargetKind::Lib(..) => "lib", TargetKind::Bin => "bin", TargetKind::Test => "integration-test", - TargetKind::Example => "example", + TargetKind::ExampleBin | + TargetKind::ExampleLib(..) => "example", TargetKind::Bench => "bench", TargetKind::CustomBuild => "build-script", }; diff --git a/src/cargo/util/toml.rs b/src/cargo/util/toml.rs index b708d18cf..a46a5a9ad 100644 --- a/src/cargo/util/toml.rs +++ b/src/cargo/util/toml.rs @@ -1159,7 +1159,16 @@ fn normalize(package_root: &Path, PathValue::Path(default(ex)) }); - let mut target = Target::example_target(&ex.name(), package_root.join(path.to_path())); + let crate_types = match ex.crate_type { + Some(ref kinds) => kinds.iter().map(|s| LibKind::from_str(s)).collect(), + None => Vec::new() + }; + + let mut target = Target::example_target( + &ex.name(), + crate_types, + package_root.join(path.to_path()) + ); configure(ex, &mut target); dst.push(target); } -- 2.30.2